#region Header
/**
 * JsonMapper.cs
 *   JSON to .Net object and object to JSON conversions.
 *
 * The authors disclaim copyright to this source code. For more details, see
 * the COPYING file included with this distribution.
 **/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
//using Extentions;

namespace CustomLitJson
{
	internal struct PropertyMetadata
	{
		public MemberInfo Info;
		public bool       IsField;
		public Type       Type;
	}

	internal struct ArrayMetadata
	{
		private Type element_type;
		private bool is_array;
		private bool is_list;

		public Type ElementType {
			get {
				if (element_type == null)
					return typeof(JsonData);

				return element_type;
			}

			set { element_type = value; }
		}

		public bool IsArray {
			get { return is_array; }
			set { is_array = value; }
		}

		public bool IsList {
			get { return is_list; }
			set { is_list = value; }
		}
	}

	internal struct ObjectMetadata
	{
		private Type element_type;
		private bool is_dictionary;
		//private IDictionary<string, PropertyMetadata> properties;
		private StringKeyDictionary<PropertyMetadata> properties;

		public Type ElementType {
			get {
				if (element_type == null)
					return typeof(JsonData);

				return element_type;
			}

			set { element_type = value; }
		}

		public bool IsDictionary {
			get { return is_dictionary; }
			set { is_dictionary = value; }
		}

		public StringKeyDictionary<PropertyMetadata> Properties {
			get { return properties; }
			set { properties = value; }
		}
	}

	internal delegate void ExporterFunc (object obj,JsonWriter writer);

	public   delegate void ExporterFunc<T> (T obj,JsonWriter writer);

	internal delegate object ImporterFunc (object input);

	public   delegate TValue ImporterFunc<TJson,TValue> (TJson input);

	public delegate IJsonWrapper WrapperFactory ();

	public class JsonMapper
	{

		static private JsonMapper mInstance;
		static public JsonMapper Instance
		{
			get
			{
				if(mInstance == null)
				{
					mInstance = new JsonMapper();
				}
				return mInstance;
			}
		}
        #region Fields
		private  int max_nesting_depth;
		private  IFormatProvider datetime_format;
		private  IDictionary<Type, ExporterFunc> base_exporters_table;
		private  IDictionary<Type, ExporterFunc> custom_exporters_table;
		private  IDictionary<Type,
                IDictionary<Type, ImporterFunc>> base_importers_table;
		private  IDictionary<Type,
                IDictionary<Type, ImporterFunc>> custom_importers_table;
		private  IDictionary<Type, ArrayMetadata> array_metadata;
		private  readonly object array_metadata_lock = new Object ();
		private  IDictionary<Type,
                IDictionary<Type, MethodInfo>> conv_ops;
		private  readonly object conv_ops_lock = new Object ();
		private  IDictionary<Type, ObjectMetadata> object_metadata;
		private  readonly object object_metadata_lock = new Object ();
		private  IDictionary<Type,
                IList<PropertyMetadata>> type_properties;
		private  readonly object type_properties_lock = new Object ();
		private  JsonWriter      static_writer;
		private  readonly object static_writer_lock = new Object ();
//		private  int static_list_deep = 0;
//		private  bool static_list_dirty = true;
		
        #endregion


        #region Constructors
		public JsonMapper ()
		{
			max_nesting_depth = 100;

			array_metadata = new Dictionary<Type, ArrayMetadata> ();
			conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>> ();
			object_metadata = new Dictionary<Type, ObjectMetadata> ();
			type_properties = new Dictionary<Type,
                            IList<PropertyMetadata>> ();

			static_writer = new JsonWriter ();

			datetime_format = DateTimeFormatInfo.InvariantInfo;

			base_exporters_table = new Dictionary<Type, ExporterFunc> ();
			custom_exporters_table = new Dictionary<Type, ExporterFunc> ();

			base_importers_table = new Dictionary<Type,
                                 IDictionary<Type, ImporterFunc>> ();
			custom_importers_table = new Dictionary<Type,
                                   IDictionary<Type, ImporterFunc>> ();

			RegisterBaseExporters ();
			RegisterBaseImporters ();
		}
        #endregion


        #region Private Methods
		private  void AddArrayMetadata (Type type)
		{
			if (array_metadata.ContainsKey (type))
				return;

			ArrayMetadata data = new ArrayMetadata ();

			data.IsArray = type.IsArray;

			if (type.GetInterface ("System.Collections.IList", false) != null)
				data.IsList = true;

			foreach (PropertyInfo p_info in type.GetProperties ()) {
				if (p_info.Name != "Item")
					continue;

				ParameterInfo[] parameters = p_info.GetIndexParameters ();

				if (parameters.Length != 1)
					continue;

				if (parameters [0].ParameterType == typeof(int))
					data.ElementType = p_info.PropertyType;
			}

			lock (array_metadata_lock) {
				try {
					array_metadata.Add (type, data);
				} catch (ArgumentException) {
					return;
				}
			}
		}

		private  void AddObjectMetadata (Type type)
		{
			if (object_metadata.ContainsKey (type))
				return;

			ObjectMetadata data = new ObjectMetadata ();

			if (type.GetInterface ("System.Collections.IDictionary") != null)
				data.IsDictionary = true;


			// pzy:
			// 修改这个字典为可忽略大小写
			//data.Properties = new Dictionary<string, PropertyMetadata> ();
			data.Properties = new StringKeyDictionary<PropertyMetadata>(true);

			foreach (PropertyInfo p_info in type.GetProperties ()) {
				if (p_info.Name == "Item") {
					ParameterInfo[] parameters = p_info.GetIndexParameters ();

					if (parameters.Length != 1)
						continue;



					// pzy:
					// 修改了代码，用来支持 json 对象转换到 int 为 key 的字典
					//if (parameters[0].ParameterType == typeof(string))
					if (parameters [0].ParameterType == typeof(string) || parameters[0].ParameterType == typeof(int))
						data.ElementType = p_info.PropertyType;

					continue;
				}

				PropertyMetadata p_data = new PropertyMetadata ();
				p_data.Info = p_info;
				p_data.Type = p_info.PropertyType;

				data.Properties.Add (p_info.Name, p_data);
			}

			foreach (FieldInfo f_info in type.GetFields ()) {
				PropertyMetadata p_data = new PropertyMetadata ();
				p_data.Info = f_info;
				p_data.IsField = true;
				p_data.Type = f_info.FieldType;

				data.Properties.Add (f_info.Name, p_data);
			}

			lock (object_metadata_lock) {
				try {
					object_metadata.Add (type, data);
				} catch (ArgumentException) {
					return;
				}
			}
		}

		private  void AddTypeProperties (Type type)
		{
			if (type_properties.ContainsKey (type))
				return;

			IList<PropertyMetadata> props = new List<PropertyMetadata> ();

			foreach (PropertyInfo p_info in type.GetProperties ()) {
				if (p_info.Name == "Item")
					continue;

				PropertyMetadata p_data = new PropertyMetadata ();
				p_data.Info = p_info;
				p_data.IsField = false;
				props.Add (p_data);
			}

			foreach (FieldInfo f_info in type.GetFields ()) {
				PropertyMetadata p_data = new PropertyMetadata ();
				p_data.Info = f_info;
				p_data.IsField = true;

				props.Add (p_data);
			}

			lock (type_properties_lock) {
				try {
					type_properties.Add (type, props);
				} catch (ArgumentException) {
					return;
				}
			}
		}

		private  MethodInfo GetConvOp (Type t1, Type t2)
		{
			lock (conv_ops_lock) {
				if (! conv_ops.ContainsKey (t1))
					conv_ops.Add (t1, new Dictionary<Type, MethodInfo> ());
			}

			if (conv_ops [t1].ContainsKey (t2))
				return conv_ops [t1] [t2];

			MethodInfo op = t1.GetMethod (
                "op_Implicit", new Type[] { t2 });

			lock (conv_ops_lock) {
				try {
					conv_ops [t1].Add (t2, op);
				} catch (ArgumentException) {
					return conv_ops [t1] [t2];
				}
			}

			return op;
		}


		public  object ReadValue (Type inst_type, JsonReader reader)
		{


			if(inst_type == typeof(JsonData))
			{
				var jd = ToObject(reader);
				return jd;
			}

			reader.Read ();
			if (reader.Token == JsonToken.ArrayEnd)
				return null;

			if (reader.Token == JsonToken.Null) 
			{
				if(inst_type==typeof(System.Int64)||
					inst_type==typeof(System.Int32) ||
					inst_type==typeof(System.Double) ||
					inst_type==typeof(System.Single))
				{	
					return 0;
				}
				else if(inst_type==typeof(System.String))
				{
					return "";
				}
				else if(inst_type==typeof(System.Boolean))
				{
					return false;
				}
				return null;
			}


			if (reader.Token == JsonToken.Double ||
				reader.Token == JsonToken.Int ||
				reader.Token == JsonToken.Long||
				reader.Token == JsonToken.String ||
				reader.Token == JsonToken.Boolean) {

                // josn_type is Int32
                // reader.Token is JsonType Int
                // inst_type is enum of TableType
				Type json_type = reader.Value.GetType (); // Int32

				if (inst_type.IsAssignableFrom (json_type))
					return reader.Value;

				if(inst_type==typeof(System.Int32))
				{
					if(json_type==typeof(System.String))
					{
						int result = 0;
						Int32.TryParse(((string)reader.Value),out result);
						return result;
					}
					return System.Convert.ToInt32(reader.Value);
				}
				if (inst_type == typeof(System.UInt32))
				{
					if (json_type == typeof(System.String))
					{
						UInt32 result = 0;
						UInt32.TryParse(((string)reader.Value), out result);
						return result;
					}
					return System.Convert.ToUInt32(reader.Value);
				}
				else if(inst_type==typeof(System.Int64))
				{
					if(json_type==typeof(System.String))
					{
						long result = 0;
						Int64.TryParse(((string)reader.Value),out result);
						return result;
					}	
					return  System.Convert.ToInt64(reader.Value);
				}
				else if (inst_type == typeof(System.UInt64))
				{
					if (json_type == typeof(System.String))
					{
						UInt64 result = 0;
						UInt64.TryParse(((string)reader.Value), out result);
						return result;
					}
					return System.Convert.ToUInt64(reader.Value);

				}
				else if(inst_type==typeof(System.Single))
				{
					return System.Convert.ToSingle(reader.Value);
				}
				else if(inst_type==typeof(System.Double))
					return System.Convert.ToDouble(reader.Value);
				else if(inst_type==typeof(System.String))
				{
					return "";
				}
				else if(inst_type==typeof(System.Boolean))
				{
					if (json_type == typeof(System.String))
					{
						bool result = false;
						bool.TryParse(((string)reader.Value), out result);
						return result;
					}
					return false;
				}
                else if(inst_type.IsEnum) // pzy: 修复不能读取枚举的bug
                {
                    return reader.Value; 
                }
				return null;
			}

			object instance = null;

			if (reader.Token == JsonToken.ArrayStart) {
				//static_list_deep++;
				
				AddArrayMetadata (inst_type);
				ArrayMetadata t_data = array_metadata [inst_type];
				
				if (! t_data.IsArray && ! t_data.IsList)
				{
					/*
					throw new JsonException (String.Format (
                            "Type {0} can't act as an array:{1}",
                            inst_type, reader.Value));
                            */
					return null;
				}
					

				IList list;
				Type elem_type;

				if (! t_data.IsArray) {
					list = (IList)Activator.CreateInstance (inst_type);
					elem_type = t_data.ElementType;
				} else {
					list = new ArrayList ();
					elem_type = inst_type.GetElementType ();
				}
				

				while (true) {

					object item = ReadValue (elem_type, reader);
					if (item == null && reader.Token == JsonToken.ArrayEnd) {
						break;
					}

					if(item != null && elem_type!=item.GetType())
					{
						if((elem_type==typeof(System.Int64))&&(item.GetType()==typeof(System.Int32)))
						{
							long _temp;
							_temp=(long)((int)item);
							list.Add(_temp);
							continue;
						}

						if(elem_type==typeof(System.Single))
					 	{
							Single _s =System.Convert.ToSingle(reader.Value);
							list.Add(_s);
							continue;
						}
					} 						
					list.Add (item);

				}

				

				if (t_data.IsArray) {
					int n = list.Count;
					instance = Array.CreateInstance (elem_type, n);

					for (int i = 0; i < n; i++)
						((Array)instance).SetValue (list [i], i);
				} else
					instance = list;
			
			} else if (reader.Token == JsonToken.ObjectStart) {

				AddObjectMetadata (inst_type);
				ObjectMetadata t_data = object_metadata [inst_type];

				if(inst_type == typeof(string))
                {
					instance = "";
				}
				else
                {
					instance = Activator.CreateInstance(inst_type);
				}
				

				while (true) {
					reader.Read ();

					if (reader.Token == JsonToken.ObjectEnd)
						break;

					if (reader.Value != null) {
						string property = reader.Value as string;
						if (property == null)
							continue;

						if (t_data.Properties.ContainsKey (property)) {
							PropertyMetadata prop_data =
								t_data.Properties [property];

							if (prop_data.IsField) 
                            {
                                var value = ReadValue (prop_data.Type, reader);
                                var fieldInfo = (FieldInfo)prop_data.Info;
								fieldInfo.SetValue (instance, value);
							} 
                            else 
                            {
								PropertyInfo p_info =
									(PropertyInfo)prop_data.Info;

								if (p_info.CanWrite)
									p_info.SetValue (
										instance,
										ReadValue (prop_data.Type, reader),
										null);
								else
									ReadValue (prop_data.Type, reader);
							}

						} else {
							if (!t_data.IsDictionary) {
								reader.Read ();
								Ignore(reader);
							} else {

								// pzy:
								// 修改了代码，用来支持 json 对象转换到 int 为 key 的字典
								var keyStringValue = property;
								var keyType = GetKeyTypeOfDictionary(instance as IDictionary);
								object keyParsedValue = ParseIfNeed(keyStringValue, keyType);

								var value = ReadValue(t_data.ElementType, reader);

								((IDictionary)instance).Add (keyParsedValue, value);
							}
						}
					}
				}

			}

			return instance;
		}

		object ParseIfNeed(string value, Type targetType)
        {
			if(targetType == typeof(int))
            {
                var ret = int.Parse(value);
				return ret;
            }
            else if(targetType == typeof(string))
            {
				return value;
            }
			throw new Exception("[JsonMapper] unsupported dictioanry key type: " + targetType);
        }

		// pzy:
		// add
		Type GetKeyTypeOfDictionary(IDictionary dic)
        {
			var keyType = dic.GetType().GetGenericArguments()[0];
			return keyType;
		}

		private void Ignore(JsonReader reader)
		{
			if (reader.Token == JsonToken.ArrayStart) {
				while (true)
				{
					reader.Read ();
					if (reader.Token == JsonToken.ArrayEnd)
					{
						break;
					}
					else if(reader.Token == JsonToken.ArrayStart)
					{
						Ignore(reader);
					}
				}
			} else if (reader.Token == JsonToken.ObjectStart) {
				while (true) {
					reader.Read ();
					if (reader.Token == JsonToken.ObjectEnd)
					{
						break;
					}
					else if(reader.Token == JsonToken.ObjectStart)
					{
						Ignore(reader);
					}
				}
			}
		}
		private  IJsonWrapper ReadValue (WrapperFactory factory,
                                               JsonReader reader)
		{
			reader.Read ();

			if (reader.Token == JsonToken.ArrayEnd ||
                reader.Token == JsonToken.Null)
				return null;

			IJsonWrapper instance = factory ();

			if (reader.Token == JsonToken.String) {
				instance.SetString ((string)reader.Value);
				return instance;
			}

			if (reader.Token == JsonToken.Double) {
				instance.SetDouble ((double)reader.Value);
				return instance;
			}

			if (reader.Token == JsonToken.Int) {
				instance.SetInt ((int)reader.Value);
				return instance;
			}

			if (reader.Token == JsonToken.Long) {
				instance.SetLong ((long)reader.Value);
				return instance;
			}

			if (reader.Token == JsonToken.Boolean) {
				instance.SetBoolean ((bool)reader.Value);
				return instance;
			}

			if (reader.Token == JsonToken.ArrayStart) {
				instance.SetJsonType (JsonType.Array);

				while (true) {
					IJsonWrapper item = ReadValue (factory, reader);
                    //if(item == null)
                    //{
                    //    break;
                    //}
                    if (reader.Token == JsonToken.ArrayEnd && item == null)
                    {
						break;
					}
                       

                    ((IList)instance).Add (item);
				}
			} else if (reader.Token == JsonToken.ObjectStart) {
				instance.SetJsonType (JsonType.Object);

				while (true) {
					reader.Read ();

					if (reader.Token == JsonToken.ObjectEnd)
						break;

					string property = (string)reader.Value;

					((IDictionary)instance) [property] = ReadValue (
                        factory, reader);
				}

			}

			return instance;
		}

		private  void RegisterBaseExporters ()
		{
			base_exporters_table [typeof(byte)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write (Convert.ToInt32 ((byte)obj));
			};

			base_exporters_table [typeof(char)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write (Convert.ToString ((char)obj));
			};

			base_exporters_table [typeof(DateTime)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write (Convert.ToString ((DateTime)obj,
                                                    datetime_format));
			};

			base_exporters_table [typeof(decimal)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write ((decimal)obj);
			};

			base_exporters_table [typeof(sbyte)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write (Convert.ToInt32 ((sbyte)obj));
			};

			base_exporters_table [typeof(short)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write (Convert.ToInt32 ((short)obj));
			};

			base_exporters_table [typeof(ushort)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write (Convert.ToInt32 ((ushort)obj));
			};

			base_exporters_table [typeof(uint)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write (Convert.ToUInt64 ((uint)obj));
			};

			base_exporters_table [typeof(ulong)] =
                delegate (object obj, JsonWriter writer) {
				writer.Write ((ulong)obj);
			};
		}

		private  void RegisterBaseImporters ()
		{
			ImporterFunc importer;

			importer = delegate (object input) {
				return Convert.ToByte ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(byte), importer);

			importer = delegate (object input) {
				return Convert.ToUInt64 ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(ulong), importer);

			importer = delegate (object input) {
				return Convert.ToSByte ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(sbyte), importer);

			importer = delegate (object input) {
				return Convert.ToInt16 ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(short), importer);

			importer = delegate (object input) {
				return Convert.ToUInt16 ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(ushort), importer);

			importer = delegate (object input) {
				return Convert.ToUInt32 ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(uint), importer);

			importer = delegate (object input) {
				return Convert.ToSingle ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(float), importer);

			importer = delegate (object input) {
				return Convert.ToDouble ((int)input);
			};
			RegisterImporter (base_importers_table, typeof(int),
                              typeof(double), importer);

			importer = delegate (object input) {
				return Convert.ToDecimal ((double)input);
			};
			RegisterImporter (base_importers_table, typeof(double),
                              typeof(decimal), importer);


			importer = delegate (object input) {
				return Convert.ToUInt32 ((long)input);
			};
			RegisterImporter (base_importers_table, typeof(long),
                              typeof(uint), importer);

			importer = delegate (object input) {
				return Convert.ToChar ((string)input);
			};
			RegisterImporter (base_importers_table, typeof(string),
                              typeof(char), importer);

			importer = delegate (object input) {
				return Convert.ToDateTime ((string)input, datetime_format);
			};
			RegisterImporter (base_importers_table, typeof(string),
                              typeof(DateTime), importer);
		}

		private  void RegisterImporter (
            IDictionary<Type, IDictionary<Type, ImporterFunc>> table,
            Type json_type, Type value_type, ImporterFunc importer)
		{
			if (! table.ContainsKey (json_type))
				table.Add (json_type, new Dictionary<Type, ImporterFunc> ());

			table [json_type] [value_type] = importer;
		}

		private  void WriteValue (object obj, JsonWriter writer,
                                        bool writer_is_private,
                                        int depth)
		{
			if (depth > max_nesting_depth)
				throw new JsonException (
                    String.Format ("Max allowed object depth reached while " +
                                   "trying to export from type {0}",
                                   obj.GetType ()));

			if (obj == null) {
				writer.Write (null);
				return;
			}

			if (obj is IJsonWrapper) {
				if (writer_is_private)
					writer.TextWriter.Write (((IJsonWrapper)obj).ToJson ());
				else
					((IJsonWrapper)obj).ToJson (writer);

				return;
			}

			if (obj is String) {
				writer.Write ((string)obj);
				return;
			}

			if (obj is Double) {
				writer.Write ((double)obj);
				return;
			}

			if (obj is Int32) {
				writer.Write ((int)obj);
				return;
			}

			if (obj is Boolean) {
				writer.Write ((bool)obj);
				return;
			}

			if (obj is Int64) {
				writer.Write ((long)obj);
				return;
			}

			if (obj is Array) {
				writer.WriteArrayStart ();

				foreach (object elem in (Array) obj)
					WriteValue (elem, writer, writer_is_private, depth + 1);

				writer.WriteArrayEnd ();

				return;
			}

			if (obj is IList) {
				writer.WriteArrayStart ();
				foreach (object elem in (IList) obj)
					WriteValue (elem, writer, writer_is_private, depth + 1);
				writer.WriteArrayEnd ();

				return;
			}

			if (obj is IDictionary) {
				writer.WriteObjectStart ();
				foreach (DictionaryEntry entry in (IDictionary) obj) {

					// pzy: 
                    //writer.WritePropertyName ((string)entry.Key);
                    string key = string.Empty;
                    if (entry.Key is string)
                    {
                        key = entry.Key as string;
                    }
                    else if (entry.Key is int)
                    {
                        key = entry.Key.ToString();
                    }
                    writer.WritePropertyName(key);

                    WriteValue (entry.Value, writer, writer_is_private,
                                depth + 1);
				}
				writer.WriteObjectEnd ();

				return;
			}

			Type obj_type = obj.GetType ();

			// See if there's a custom exporter for the object
			if (custom_exporters_table.ContainsKey (obj_type)) {
				ExporterFunc exporter = custom_exporters_table [obj_type];
				exporter (obj, writer);

				return;
			}

			// If not, maybe there's a base exporter
			if (base_exporters_table.ContainsKey (obj_type)) {
				ExporterFunc exporter = base_exporters_table [obj_type];
				exporter (obj, writer);

				return;
			}

			// Last option, let's see if it's an enum
			if (obj is Enum) {
				Type e_type = Enum.GetUnderlyingType (obj_type);

				if (e_type == typeof(long)
                    || e_type == typeof(uint)
                    || e_type == typeof(ulong))
					writer.Write ((ulong)obj);
				else
					writer.Write ((int)obj);

				return;
			}

			// Okay, so it looks like the input should be exported as an
			// object
			AddTypeProperties (obj_type);
			IList<PropertyMetadata> props = type_properties [obj_type];

			writer.WriteObjectStart ();
			foreach (PropertyMetadata p_data in props) {
				if (p_data.IsField) {
					writer.WritePropertyName (p_data.Info.Name);
					WriteValue (((FieldInfo)p_data.Info).GetValue (obj),
                                writer, writer_is_private, depth + 1);
				} else {
					PropertyInfo p_info = (PropertyInfo)p_data.Info;

					if (p_info.CanRead) {
						writer.WritePropertyName (p_data.Info.Name);
						WriteValue (p_info.GetValue (obj, null),
                                    writer, writer_is_private, depth + 1);
					}
				}
			}
			writer.WriteObjectEnd ();
		}
        #endregion


		public  string ToJson (object obj)
		{
			if(obj == null)
			{
				return "null";
			}
			lock (static_writer_lock) {
				static_writer.Reset ();

				WriteValue (obj, static_writer, true, 0);

				return static_writer.ToString ();
			}
		}

		public  void ToJson (object obj, JsonWriter writer)
		{
			WriteValue (obj, writer, false, 0);
		}

		public  JsonData ToObject (JsonReader reader)
		{
			return (JsonData)ToWrapper (
                delegate {
				return new JsonData (); }, reader);
		}

		public  JsonData ToObject (TextReader reader)
		{
			JsonReader json_reader = new JsonReader (reader);

			return (JsonData)ToWrapper (
                delegate {
				return new JsonData (); }, json_reader);
		}

		public  JsonData ToObject (string json)
		{
			return (JsonData)ToWrapper (
                delegate {
				return new JsonData (); }, json);
		}

		public  T ToObject<T> (JsonReader reader)
		{
			return (T)ReadValue (typeof(T), reader);
		}

		public  T ToObject<T> (TextReader reader)
		{
			JsonReader json_reader = new JsonReader (reader);

			return (T)ReadValue (typeof(T), json_reader);
		}

		public  T ToObject<T> (string json)
		{
			JsonReader reader = new JsonReader (json);

			return (T)ReadValue (typeof(T), reader);
		}

		public  IJsonWrapper ToWrapper (WrapperFactory factory,
                                              JsonReader reader)
		{
			return ReadValue (factory, reader);
		}

		public  IJsonWrapper ToWrapper (WrapperFactory factory,
                                              string json)
		{
			JsonReader reader = new JsonReader (json);

			return ReadValue (factory, reader);
		}

		public  void RegisterExporter<T> (ExporterFunc<T> exporter)
		{
			ExporterFunc exporter_wrapper =
                delegate (object obj, JsonWriter writer) {
				exporter ((T)obj, writer);
			};

			custom_exporters_table [typeof(T)] = exporter_wrapper;
		}

		public  void RegisterImporter<TJson, TValue> (
            ImporterFunc<TJson, TValue> importer)
		{
			ImporterFunc importer_wrapper =
                delegate (object input) {
				return importer ((TJson)input);
			};

			RegisterImporter (custom_importers_table, typeof(TJson),
                              typeof(TValue), importer_wrapper);
		}

		public  void UnregisterExporters ()
		{
			custom_exporters_table.Clear ();
		}

		public  void UnregisterImporters ()
		{
			custom_importers_table.Clear ();
		}

	}

	public static class JsonMapperExtend
	{
//		static public string ToJson (object obj)
//		{
//			return JsonMapper.Instance.ToJson(obj);
//		}
//		
//		static public  void ToJson (object obj, JsonWriter writer)
//		{
//			JsonMapper.Instance.ToJson (obj, writer);
//		}
//		
//		static public  JsonData ToObject (JsonReader reader)
//		{
//			return JsonMapper.Instance.ToObject(reader);
//		}
//
//		static public  JsonData ToObject (TextReader reader)
//		{
//			return JsonMapper.Instance.ToObject(reader);
//		}
//		
//		static public  JsonData ToObject (string json)
//		{
//			return JsonMapper.Instance.ToObject (json);
//		}
//		
//		static public  T ToObject<T> (JsonReader reader)
//		{
//			return JsonMapper.Instance.ToObject<T> (reader);
//		}
//		
//		static public  T ToObject<T> (TextReader reader)
//		{
//			return JsonMapper.Instance.ToObject<T> (reader);
//		}
//
//		static public  T ToObject<T> (string json)
//		{
//			return JsonMapper.Instance.ToObject<T> (json);
//		}
		
		static public  object ToObject(this JsonMapper jm,System.Type type, string json)
		{
			return JsonMapper.Instance.ReadValue(type, new JsonReader( json ));
		}
		

	}
}
